home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / framewin.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-03  |  43.5 KB  |  1,582 lines

  1. /* 
  2.  *  Window Maker window manager
  3.  * 
  4.  *  Copyright (c) 1997, 1998 Alfredo K. Kojima
  5.  * 
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  19.  *  USA.
  20.  */
  21.  
  22. #include "wconfig.h"
  23.  
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #ifdef KEEP_XKB_LOCK_STATUS     
  27. #include <X11/XKBlib.h>         
  28. #endif /* KEEP_XKB_LOCK_STATUS */
  29.  
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include <wraster.h>
  34.  
  35. #include "WindowMaker.h"
  36. #include "GNUstep.h"
  37. #include "texture.h"
  38. #include "screen.h"
  39. #include "wcore.h"
  40. #include "framewin.h"
  41. #include "stacking.h"
  42. #include "funcs.h"
  43.  
  44. #define DBLCLICK_TIME wPreferences.dblclick_time
  45.  
  46. extern WPreferences wPreferences;
  47.  
  48. static void handleExpose(WObjDescriptor *desc, XEvent *event);
  49. static void handleButtonExpose(WObjDescriptor *desc, XEvent *event);
  50.  
  51. static void buttonMouseDown(WObjDescriptor *desc, XEvent *event);
  52. static void titlebarMouseDown(WObjDescriptor *desc, XEvent *event);
  53. static void resizebarMouseDown(WObjDescriptor *desc, XEvent *event);
  54.  
  55. static void checkTitleSize(WFrameWindow *fwin);
  56.  
  57.  
  58. static void paintButton(WCoreWindow *button, WTexture *texture, 
  59.             unsigned long color,  WPixmap *image, int pushed);
  60.  
  61. static void updateTitlebar(WFrameWindow *fwin);
  62.  
  63.  
  64. WFrameWindow*
  65. wFrameWindowCreate(WScreen *scr, int wlevel, int x, int y, 
  66.            int width, int height, int *clearance, int flags,
  67.            WTexture **title_texture, WTexture **resize_texture,
  68.            unsigned long *color,
  69. #ifdef DRAWSTRING_PLUGIN
  70.            int function_offset,
  71. #endif
  72.            GC *gc, WMFont **font)
  73. {
  74.     WFrameWindow *fwin;
  75.     
  76.     fwin = wmalloc(sizeof(WFrameWindow));
  77.     memset(fwin, 0, sizeof(WFrameWindow));
  78.     
  79.     fwin->screen_ptr = scr;
  80.  
  81.     fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
  82.     
  83.     fwin->title_texture = title_texture;
  84.     fwin->resizebar_texture = resize_texture;
  85.     fwin->title_pixel = color;
  86.     fwin->title_clearance = clearance;
  87. #ifdef DRAWSTRING_PLUGIN
  88.     fwin->drawstring_proc_offset = function_offset;
  89. #endif
  90.     fwin->title_gc = gc;
  91.     fwin->font = font;
  92. #ifdef KEEP_XKB_LOCK_STATUS
  93.     fwin->languagemode = XkbGroup1Index;
  94.     fwin->last_languagemode = XkbGroup2Index;
  95. #endif
  96.  
  97.     fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, 
  98.                      (flags & WFF_BORDER) 
  99.                      ? FRAME_BORDER_WIDTH : 0);
  100.     if (wPreferences.use_saveunders) {
  101.     unsigned long vmask;
  102.     XSetWindowAttributes attribs;
  103.     
  104.     vmask = CWSaveUnder;
  105.     attribs.save_under = True;
  106.     XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
  107.     }
  108.     
  109.     /* setup stacking information */
  110.     fwin->core->stacking = wmalloc(sizeof(WStacking));
  111.     fwin->core->stacking->above = NULL;
  112.     fwin->core->stacking->under = NULL;
  113.     fwin->core->stacking->child_of = NULL;
  114.     fwin->core->stacking->window_level = wlevel;
  115.     
  116.     AddToStackList(fwin->core);
  117.     
  118.     wFrameWindowUpdateBorders(fwin, flags);
  119.     
  120.     return fwin;
  121. }
  122.  
  123.  
  124.  
  125. void
  126. wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags)
  127. {
  128.     int theight;
  129.     int bsize;
  130.     int width, height;
  131.     int i;
  132.     WScreen *scr = fwin->screen_ptr;
  133.  
  134.     width = fwin->core->width;
  135.     if (flags & WFF_IS_SHADED)
  136.     height = -1;
  137.     else
  138.     height = fwin->core->height - fwin->top_width - fwin->bottom_width;
  139.  
  140.     if (flags & WFF_TITLEBAR)
  141.     theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
  142.     else
  143.     theight = 0;
  144.     
  145.     if (wPreferences.new_style) {
  146.     bsize = theight;
  147.     } else {
  148.     bsize = theight - 7;
  149.     }
  150.     
  151.     if (fwin->titlebar) {
  152.     /* if we had a titlebar and is requesting for one,
  153.      * check if the size has changed and resize it */
  154.     if (flags & WFF_TITLEBAR) {
  155.         fwin->top_width = theight;
  156.  
  157.         fwin->flags.need_texture_remake = 1;
  158.         
  159.         if (wPreferences.new_style) {
  160.         if (fwin->left_button) {
  161.             wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
  162.         }
  163. #ifdef XKB_BUTTON_HINT
  164.         if (fwin->language_button)
  165.             if (fwin->flags.hide_left_button || !fwin->left_button
  166.             || fwin->flags.lbutton_dont_fit) {
  167.             wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
  168.             } else {
  169.             wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
  170.             }
  171. #endif
  172.  
  173.         
  174.         if (fwin->right_button) {
  175.             wCoreConfigure(fwin->right_button, width-bsize+1,
  176.                    0, bsize, bsize);
  177.         }
  178.         } else { /* !new_style */
  179.         if (fwin->left_button) {
  180.             wCoreConfigure(fwin->left_button, 3, (theight-bsize)/2,
  181.                    bsize, bsize);
  182.         }
  183.         
  184. #ifdef XKB_BUTTON_HINT
  185.         if (fwin->language_button) {
  186.             wCoreConfigure(fwin->language_button, 6 + bsize, (theight-bsize)/2,
  187.                    bsize, bsize);
  188.         }
  189. #endif
  190.         
  191.         if (fwin->right_button) {
  192.             wCoreConfigure(fwin->right_button, width-bsize-3,
  193.                    (theight-bsize)/2, bsize, bsize);
  194.         }
  195.         }
  196.         updateTitlebar(fwin);
  197.     } else {
  198.         /* we had a titlebar, but now we don't need it anymore */
  199.         for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
  200.         FREE_PIXMAP(fwin->title_back[i]);
  201.         if (wPreferences.new_style) {
  202.             FREE_PIXMAP(fwin->lbutton_back[i]);
  203.             FREE_PIXMAP(fwin->rbutton_back[i]);
  204. #ifdef XKB_BUTTON_HINT
  205.             FREE_PIXMAP(fwin->languagebutton_back[i]);
  206. #endif
  207.         }
  208.         }
  209.         if (fwin->left_button)
  210.         wCoreDestroy(fwin->left_button);
  211.         fwin->left_button = NULL;
  212.         
  213. #ifdef XKB_BUTTON_HINT
  214.         if (fwin->language_button)
  215.         wCoreDestroy(fwin->language_button);
  216.         fwin->language_button = NULL;
  217. #endif
  218.  
  219.         if (fwin->right_button)
  220.         wCoreDestroy(fwin->right_button);
  221.         fwin->right_button = NULL;
  222.         
  223.         wCoreDestroy(fwin->titlebar);
  224.         fwin->titlebar = NULL;
  225.         
  226.         fwin->top_width = 0;
  227.     }
  228.     } else {
  229.     /* if we didn't have a titlebar and are being requested for
  230.      * one, create it */
  231.     if (flags & WFF_TITLEBAR) {        
  232.         fwin->top_width = theight;
  233.         
  234.         fwin->flags.titlebar = 1;
  235.         fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width+1, theight);
  236.  
  237.         if (flags & WFF_LEFT_BUTTON) {
  238.         fwin->flags.left_button = 1;
  239.         if (wPreferences.new_style) {
  240.             fwin->left_button = wCoreCreate(fwin->core, 0, 0,
  241.                             bsize, bsize);
  242.             if (width < theight*4) {
  243.             fwin->flags.lbutton_dont_fit = 1;
  244.             } else {
  245.             XMapRaised(dpy, fwin->left_button->window);
  246.             }
  247.         } else {
  248.             fwin->left_button = 
  249.             wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
  250.                     bsize, bsize);
  251.             
  252.             XSetWindowBackground(dpy, fwin->left_button->window,
  253.                      scr->widget_texture->normal.pixel);
  254.             
  255.             if (width < theight*3) {
  256.             fwin->flags.lbutton_dont_fit = 1;
  257.             } else {
  258.             XMapRaised(dpy, fwin->left_button->window);
  259.             }
  260.         }
  261.         }
  262.         
  263. #ifdef XKB_BUTTON_HINT
  264.         if (flags & WFF_LANGUAGE_BUTTON) {
  265.         fwin->flags.language_button = 1;
  266.         if (wPreferences.new_style) {
  267.             fwin->language_button = wCoreCreate(fwin->core,
  268.                             bsize, 0, bsize, bsize);
  269.             
  270.             if (width < theight*4) {
  271.             fwin->flags.languagebutton_dont_fit = 1;
  272.             } else {
  273.             XMapRaised(dpy, fwin->language_button->window);
  274.             }
  275.         } else {
  276.             fwin->language_button = 
  277.             wCoreCreate(fwin->titlebar, bsize + 6, (theight-bsize)/2,
  278.                     bsize, bsize); 
  279.             
  280.             XSetWindowBackground(dpy, fwin->language_button->window,
  281.                      scr->widget_texture->normal.pixel); 
  282.             
  283.             if (width < theight*3) {
  284.             fwin->flags.languagebutton_dont_fit = 1;
  285.             } else {
  286.             XMapRaised(dpy, fwin->language_button->window);
  287.             }
  288.         }
  289.         }
  290. #endif
  291.         
  292.         if (flags & WFF_RIGHT_BUTTON) {
  293.         fwin->flags.right_button = 1;
  294.                 if (wPreferences.new_style) {
  295.             fwin->right_button =
  296.             wCoreCreate(fwin->core, width-bsize+1, 0,
  297.                     bsize, bsize);
  298.                 } else {
  299.             fwin->right_button =
  300.             wCoreCreate(fwin->titlebar, width-bsize-3,
  301.                     (theight-bsize)/2, bsize, bsize);
  302.             XSetWindowBackground(dpy, fwin->right_button->window,
  303.                      scr->widget_texture->normal.pixel);
  304.                 }
  305.         
  306.         if (width < theight*2) {
  307.             fwin->flags.rbutton_dont_fit = 1;
  308.         } else {
  309.             XMapRaised(dpy, fwin->right_button->window);
  310.         }
  311.         }
  312.         
  313.             if (wPreferences.new_style)
  314.         updateTitlebar(fwin);
  315.  
  316.         XMapRaised(dpy, fwin->titlebar->window);
  317.  
  318.         fwin->flags.need_texture_remake = 1;
  319.     }
  320.     }
  321.     checkTitleSize(fwin);
  322.     
  323.     if (flags & WFF_RESIZEBAR) {
  324.     fwin->bottom_width = RESIZEBAR_HEIGHT;
  325.     
  326.     if (!fwin->resizebar) {
  327.         fwin->flags.resizebar = 1;
  328.         fwin->resizebar = wCoreCreate(fwin->core, 0,
  329.                       height + fwin->top_width,
  330.                       width, RESIZEBAR_HEIGHT);
  331.         fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
  332.         if (width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
  333.         fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH)/2;
  334.         if (fwin->resizebar_corner_width < 0)
  335.             fwin->resizebar_corner_width = 0;
  336.         }
  337.         
  338.         XMapWindow(dpy, fwin->resizebar->window);
  339.         XLowerWindow(dpy, fwin->resizebar->window);
  340.         
  341.         fwin->flags.need_texture_remake = 1;
  342.     } else {
  343.         if (height+fwin->top_width+fwin->bottom_width != fwin->core->height) {
  344.         wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
  345.                    width, RESIZEBAR_HEIGHT);
  346.         }
  347.     }
  348.     } else {
  349.     fwin->bottom_width = 0;
  350.     
  351.     if (fwin->resizebar) {
  352.         fwin->bottom_width = 0;
  353.         wCoreDestroy(fwin->resizebar);
  354.         fwin->resizebar = NULL;
  355.     }
  356.     }
  357.  
  358.     if (height + fwin->top_width + fwin->bottom_width != fwin->core->height
  359.     && !(flags & WFF_IS_SHADED)) {
  360.     wFrameWindowResize(fwin, width,
  361.                height + fwin->top_width + fwin->bottom_width);
  362.     }
  363.     
  364.     
  365.     if (flags & WFF_BORDER) {
  366.     XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
  367.     } else {
  368.     XSetWindowBorderWidth(dpy, fwin->core->window, 0);
  369.     }
  370.     
  371.     /* setup object descriptors */
  372.     
  373.     if (fwin->titlebar) {
  374.     fwin->titlebar->descriptor.handle_expose = handleExpose;
  375.     fwin->titlebar->descriptor.parent = fwin;
  376.     fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
  377.     fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
  378.     }
  379.     
  380.     if (fwin->resizebar) {
  381.     fwin->resizebar->descriptor.handle_expose = handleExpose;
  382.     fwin->resizebar->descriptor.parent = fwin;
  383.     fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
  384.     fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
  385.     }
  386.     
  387.     if (fwin->left_button) {
  388.     fwin->left_button->descriptor.handle_expose = handleButtonExpose;
  389.     fwin->left_button->descriptor.parent = fwin;
  390.     fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
  391.     fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
  392.     }
  393.     
  394. #ifdef XKB_BUTTON_HINT
  395.     if (fwin->language_button) {
  396.     fwin->language_button->descriptor.handle_expose = handleButtonExpose;
  397.     fwin->language_button->descriptor.parent = fwin;
  398.     fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
  399.     fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
  400.     }
  401. #endif
  402.  
  403.     
  404.     if (fwin->right_button) {
  405.     fwin->right_button->descriptor.parent = fwin;
  406.     fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
  407.     fwin->right_button->descriptor.handle_expose = handleButtonExpose;
  408.     fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
  409.     }
  410.     
  411.     checkTitleSize(fwin);
  412. }
  413.  
  414.  
  415.  
  416. void 
  417. wFrameWindowDestroy(WFrameWindow *fwin)
  418. {
  419.     int i;
  420.     
  421.     if (fwin->left_button)
  422.     wCoreDestroy(fwin->left_button);
  423.     
  424. #ifdef XKB_BUTTON_HINT
  425.     if (fwin->language_button)
  426.     wCoreDestroy(fwin->language_button);
  427. #endif
  428.     
  429.     if (fwin->right_button)
  430.     wCoreDestroy(fwin->right_button);
  431.     
  432.     if (fwin->resizebar)
  433.     wCoreDestroy(fwin->resizebar);
  434.     
  435.     if (fwin->titlebar)
  436.     wCoreDestroy(fwin->titlebar);
  437.     
  438.     RemoveFromStackList(fwin->core);
  439.     
  440.     wCoreDestroy(fwin->core);
  441.     
  442.     if (fwin->title)
  443.     free(fwin->title);
  444.     
  445.     for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
  446.     FREE_PIXMAP(fwin->title_back[i]);
  447.         if (wPreferences.new_style) {
  448.         FREE_PIXMAP(fwin->lbutton_back[i]);
  449. #ifdef XKB_BUTTON_HINT
  450.         FREE_PIXMAP(fwin->languagebutton_back[i]);
  451. #endif
  452.         FREE_PIXMAP(fwin->rbutton_back[i]);
  453.         }
  454.     }
  455.     
  456.     free(fwin);
  457. }
  458.  
  459.  
  460. void 
  461. wFrameWindowChangeState(WFrameWindow *fwin, int state)
  462. {
  463.     if (fwin->flags.state==state)
  464.     return;
  465.     
  466.     fwin->flags.state = state;
  467.     fwin->flags.need_texture_change = 1;
  468.     
  469.     wFrameWindowPaint(fwin);
  470. }
  471.  
  472.  
  473. static void
  474. updateTitlebar(WFrameWindow *fwin)
  475. {
  476.     int x, w;
  477.     int theight;
  478.     
  479.     theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
  480.  
  481.     x = 0;
  482.     w = fwin->core->width + 1;
  483.  
  484.     if (wPreferences.new_style) {
  485.     if (fwin->flags.hide_left_button || !fwin->left_button
  486.         || fwin->flags.lbutton_dont_fit) {
  487.         x = 0;
  488. #ifdef XKB_BUTTON_HINT
  489.         if(fwin->language_button)
  490.             wCoreConfigure(fwin->language_button, 0, 0,
  491.                     fwin->language_button->width,
  492.                     fwin->language_button->width);
  493. #endif
  494.     } else {
  495. #ifdef XKB_BUTTON_HINT
  496.         if(fwin->language_button)
  497.             wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
  498.                     fwin->language_button->width,
  499.                     fwin->language_button->width);
  500. #endif
  501.         x = fwin->left_button->width;
  502.         w -= fwin->left_button->width;
  503.     }
  504. #ifdef XKB_BUTTON_HINT
  505.     if (fwin->flags.hide_language_button || !fwin->language_button
  506.         || fwin->flags.languagebutton_dont_fit) {
  507.     } else {
  508.         x += fwin->language_button->width;
  509.         w -= fwin->language_button->width;
  510.     }
  511. #endif
  512.     }
  513. #ifdef XKB_BUTTON_HINT
  514.     else {
  515.         int bsize = theight - 7;
  516.         if (fwin->flags.hide_left_button || !fwin->left_button
  517.             || fwin->flags.lbutton_dont_fit) {
  518.             if(fwin->language_button)
  519.                 wCoreConfigure(fwin->language_button, 3, (theight-bsize)/2,
  520.                         fwin->language_button->width,
  521.                         fwin->language_button->width);
  522.         }
  523.         else {
  524.             if(fwin->language_button)
  525.                 wCoreConfigure(fwin->language_button,
  526.                         6 + fwin->left_button->width, (theight-bsize)/2,
  527.                         fwin->language_button->width,
  528.                         fwin->language_button->width);
  529.         }
  530.     }
  531. #endif
  532.     
  533.     if (wPreferences.new_style) {
  534.     if (!fwin->flags.hide_right_button && fwin->right_button
  535.         && !fwin->flags.rbutton_dont_fit) {
  536.         w -= fwin->right_button->width;
  537.     }
  538.     }
  539.  
  540.     if (wPreferences.new_style || fwin->titlebar->width!=w)
  541.     fwin->flags.need_texture_remake = 1;
  542.  
  543.     wCoreConfigure(fwin->titlebar, x, 0, w, theight);
  544. }
  545.  
  546.  
  547. void
  548. wFrameWindowHideButton(WFrameWindow *fwin, int flags)
  549. {
  550.     if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
  551.     XUnmapWindow(dpy, fwin->right_button->window);
  552.     fwin->flags.hide_right_button = 1;
  553.     }
  554.     
  555.     if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
  556.     XUnmapWindow(dpy, fwin->left_button->window);
  557.     fwin->flags.hide_left_button = 1;
  558.     }
  559.     
  560. #ifdef XKB_BUTTON_HINT
  561.     if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
  562.     XUnmapWindow(dpy, fwin->language_button->window);
  563.     fwin->flags.hide_language_button = 1;
  564.     }
  565. #endif
  566.  
  567.     if (fwin->titlebar) {
  568.     if (wPreferences.new_style) {
  569.         updateTitlebar(fwin);
  570.     } else {
  571. #ifdef XKB_BUTTON_HINT
  572.         updateTitlebar(fwin);
  573. #else
  574.         XClearWindow(dpy, fwin->titlebar->window);
  575.         wFrameWindowPaint(fwin);
  576. #endif
  577.     }
  578.     checkTitleSize(fwin);
  579.     }
  580. }
  581.  
  582.  
  583. void
  584. wFrameWindowShowButton(WFrameWindow *fwin, int flags)
  585. {
  586.     if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button
  587.     && fwin->flags.hide_right_button) {
  588.     
  589.     if (!fwin->flags.rbutton_dont_fit)
  590.         XMapWindow(dpy, fwin->right_button->window);
  591.     
  592.     fwin->flags.hide_right_button = 0;
  593.     }
  594.  
  595. #ifdef XKB_BUTTON_HINT
  596.     if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button
  597.     && fwin->flags.hide_language_button) {
  598.     
  599.     if (!fwin->flags.languagebutton_dont_fit)
  600.         XMapWindow(dpy, fwin->language_button->window);
  601.     
  602.     fwin->flags.hide_language_button = 0;
  603.     }
  604. #endif
  605.     
  606.     if ((flags & WFF_LEFT_BUTTON) && fwin->left_button
  607.     && fwin->flags.hide_left_button) {
  608.     
  609.     if (!fwin->flags.lbutton_dont_fit)
  610.         XMapWindow(dpy, fwin->left_button->window);
  611.     
  612.     fwin->flags.hide_left_button = 0;
  613.     }
  614.  
  615.     
  616.     if (fwin->titlebar) {
  617.     if (wPreferences.new_style) {
  618.         updateTitlebar(fwin);
  619.     } else {
  620.         XClearWindow(dpy, fwin->titlebar->window);
  621.         wFrameWindowPaint(fwin);
  622.     }
  623.     checkTitleSize(fwin);
  624.     }
  625. }
  626.  
  627.  
  628. static void
  629. #ifdef XKB_BUTTON_HINT
  630. renderTexture(WScreen *scr, WTexture *texture, int width, int height, 
  631.           int bwidth, int bheight, int left, int language, int right,
  632.           Pixmap *title, Pixmap *lbutton, Pixmap *languagebutton, Pixmap *rbutton)
  633. #else
  634. renderTexture(WScreen *scr, WTexture *texture, int width, int height, 
  635.           int bwidth, int bheight, int left, int right,
  636.           Pixmap *title, Pixmap *lbutton, Pixmap *rbutton)
  637. #endif
  638. {
  639.     RImage *img;
  640.     RImage *limg, *rimg, *mimg;
  641. #ifdef XKB_BUTTON_HINT
  642.     RImage *timg;
  643. #endif
  644.     int x, w;
  645.  
  646.     *title = None;
  647.     *lbutton = None;
  648.     *rbutton = None;
  649. #ifdef XKB_BUTTON_HINT
  650.     *languagebutton = None;
  651. #endif
  652.  
  653.     img = wTextureRenderImage(texture, width, height, WREL_FLAT);
  654.     if (!img) {
  655.         wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
  656.         return;
  657.     }
  658.     
  659.     if (wPreferences.new_style) {
  660.     if (left) {
  661.         limg = RGetSubImage(img, 0, 0, bwidth, bheight);
  662.     } else
  663.         limg = NULL;
  664.     
  665.     x = 0;
  666.     w = img->width;
  667.     
  668. #ifdef XKB_BUTTON_HINT
  669.     if (language) {
  670.         timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
  671.     } else
  672.         timg = NULL;
  673. #endif
  674.     
  675.     if (limg) {
  676.         RBevelImage(limg, RBEV_RAISED2);
  677.         if (!RConvertImage(scr->rcontext, limg, lbutton)) {
  678.         wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  679.         }
  680.         x += limg->width;
  681.         w -= limg->width;
  682.         RDestroyImage(limg);
  683.     }
  684.  
  685. #ifdef XKB_BUTTON_HINT
  686.     if (timg) {
  687.         RBevelImage(timg, RBEV_RAISED2);
  688.         if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
  689.         wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  690.         }
  691.         x += timg->width;
  692.         w -= timg->width;
  693.         RDestroyImage(timg);
  694.     }
  695. #endif
  696.     
  697.     if (right) {
  698.         rimg = RGetSubImage(img, width - bwidth, 0,    bwidth, bheight);
  699.     } else
  700.         rimg = NULL;
  701.     
  702.     if (rimg) {
  703.         RBevelImage(rimg, RBEV_RAISED2);
  704.         if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
  705.         wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  706.         }
  707.         w -= rimg->width;
  708.         RDestroyImage(rimg);
  709.     }
  710.     
  711.     if (w!=width) {
  712.         mimg = RGetSubImage(img, x, 0, w, img->height);
  713.         RBevelImage(mimg, RBEV_RAISED2);
  714.  
  715.         if (!RConvertImage(scr->rcontext, mimg, title)) {
  716.         wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  717.         }
  718.         RDestroyImage(mimg);
  719.     } else {
  720.         RBevelImage(img, RBEV_RAISED2);
  721.         
  722.         if (!RConvertImage(scr->rcontext, img, title)) {
  723.         wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  724.         }
  725.     }
  726.     } else {
  727.     RBevelImage(img, RBEV_RAISED2);
  728.  
  729.     if (!RConvertImage(scr->rcontext, img, title)) {
  730.         wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
  731.     }
  732.     }
  733.  
  734.     RDestroyImage(img);
  735. }
  736.  
  737.  
  738. static void
  739. renderResizebarTexture(WScreen *scr, WTexture *texture, int width, int height,
  740.                int cwidth, Pixmap *pmap)
  741. {
  742.     RImage *img;
  743.     RColor light;
  744.     RColor dark;
  745.  
  746.     *pmap = None;
  747.  
  748.     img = wTextureRenderImage(texture, width, height, WREL_FLAT);
  749.     if (!img) {
  750.         wwarning(_("could not render texture: %s"),
  751.          RMessageForError(RErrorCode));
  752.         return;
  753.     }
  754.  
  755.     light.alpha = 0;
  756.     light.red = light.green = light.blue = 80;
  757.  
  758.     dark.alpha = 0;
  759.     dark.red = dark.green = dark.blue = 40;
  760.  
  761.     ROperateLine(img, RSubtractOperation, 0, 0, width-1, 0, &dark);
  762.     ROperateLine(img, RAddOperation, 0, 1, width-1, 1, &light);
  763.  
  764.     ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height-1, &dark);
  765.     ROperateLine(img, RAddOperation, cwidth+1, 2, cwidth+1, height-1, &light);
  766.  
  767.     if (width > 1)
  768.     ROperateLine(img, RSubtractOperation, width-cwidth-2, 2, 
  769.              width-cwidth-2, height-1, &dark);
  770.     ROperateLine(img, RAddOperation, width-cwidth-1, 2, width-cwidth-1, 
  771.          height-1, &light);
  772.  
  773. #ifdef SHADOW_RESIZEBAR
  774.     ROperateLine(img, RAddOperation, 0, 1, 0, height-1, &light);
  775.     ROperateLine(img, RSubtractOperation, width-1, 1, width-1, height-1,
  776.          &dark);
  777.     ROperateLine(img, RSubtractOperation, 0, height-1, width-1, height-1,
  778.          &dark);
  779. #endif /* SHADOW_RESIZEBAR */
  780.  
  781.  
  782.     if (!RConvertImage(scr->rcontext, img, pmap)) {
  783.     wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
  784.     }
  785.  
  786.     RDestroyImage(img);
  787. }
  788.  
  789.  
  790.  
  791. static void
  792. updateTexture(WFrameWindow *fwin)
  793. {
  794.     int i;
  795.     unsigned long pixel;
  796.         
  797.     i = fwin->flags.state;
  798.     if (fwin->titlebar) {
  799.     if (fwin->title_texture[i]->any.type!=WTEX_SOLID) {
  800.         XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window,
  801.                        fwin->title_back[i]);
  802.         if (wPreferences.new_style) {
  803.         if (fwin->left_button && fwin->lbutton_back[i])
  804.             XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
  805.                            fwin->lbutton_back[i]);
  806.  
  807. #ifdef XKB_BUTTON_HINT
  808.         if (fwin->language_button && fwin->languagebutton_back[i]) {
  809.             XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
  810.                            fwin->languagebutton_back[i]);
  811.         }
  812. #endif
  813.         
  814.         if (fwin->right_button && fwin->rbutton_back[i])
  815.             XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
  816.                            fwin->rbutton_back[i]);
  817.         }
  818.     } else {
  819.         pixel = fwin->title_texture[i]->solid.normal.pixel;
  820.         XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
  821.         if (wPreferences.new_style) {
  822.         if (fwin->left_button)
  823.             XSetWindowBackground(dpy, fwin->left_button->window,
  824.                      pixel);
  825. #ifdef XKB_BUTTON_HINT
  826.         if (fwin->language_button)
  827.             XSetWindowBackground(dpy, fwin->language_button->window,
  828.                      pixel);
  829. #endif
  830.         if (fwin->right_button)
  831.             XSetWindowBackground(dpy, fwin->right_button->window,
  832.                      pixel);
  833.         }
  834.     }
  835.     XClearWindow(dpy, fwin->titlebar->window);
  836.     
  837.     if (fwin->left_button) {
  838.         XClearWindow(dpy, fwin->left_button->window);
  839.         handleButtonExpose(&fwin->left_button->descriptor, NULL);
  840.     }
  841. #ifdef XKB_BUTTON_HINT
  842.        if (fwin->language_button) {
  843.            XClearWindow(dpy, fwin->language_button->window);
  844.            handleButtonExpose(&fwin->language_button->descriptor, NULL);
  845.        }
  846. #endif
  847.     if (fwin->right_button) {
  848.         XClearWindow(dpy, fwin->right_button->window);
  849.         handleButtonExpose(&fwin->right_button->descriptor, NULL);
  850.     }
  851.     }
  852. }
  853.  
  854.  
  855.  
  856. static void
  857. remakeTexture(WFrameWindow *fwin, int state)
  858. {
  859.     Pixmap pmap, lpmap, rpmap;
  860. #ifdef XKB_BUTTON_HINT
  861.     Pixmap tpmap;
  862. #endif
  863.  
  864.     if (fwin->title_texture[state] && fwin->titlebar) {
  865.     FREE_PIXMAP(fwin->title_back[state]);
  866.     if (wPreferences.new_style) {
  867.         FREE_PIXMAP(fwin->lbutton_back[state]);
  868.         FREE_PIXMAP(fwin->rbutton_back[state]);
  869. #ifdef XKB_BUTTON_HINT
  870.         FREE_PIXMAP(fwin->languagebutton_back[state]);
  871. #endif
  872.     }
  873.  
  874.     if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
  875.         int left, right;
  876. #ifdef XKB_BUTTON_HINT
  877.         int language;
  878. #endif
  879.         int width;
  880.  
  881.         /* eventually surrounded by if new_style */
  882.         left = fwin->left_button && !fwin->flags.hide_left_button
  883.         && !fwin->flags.lbutton_dont_fit;
  884. #ifdef XKB_BUTTON_HINT
  885.         language = fwin->language_button && !fwin->flags.hide_language_button
  886.         && !fwin->flags.languagebutton_dont_fit;
  887. #endif
  888.         right = fwin->right_button && !fwin->flags.hide_right_button
  889.         && !fwin->flags.rbutton_dont_fit;
  890.  
  891.         width = fwin->core->width+1;
  892.  
  893. #ifdef XKB_BUTTON_HINT
  894.         renderTexture(fwin->screen_ptr, fwin->title_texture[state],
  895.               width, fwin->titlebar->height,
  896.               fwin->titlebar->height, fwin->titlebar->height,
  897.               left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
  898. #else
  899.         renderTexture(fwin->screen_ptr, fwin->title_texture[state],
  900.               width, fwin->titlebar->height,
  901.               fwin->titlebar->height, fwin->titlebar->height,
  902.               left, right, &pmap, &lpmap, &rpmap);
  903. #endif
  904.  
  905.         fwin->title_back[state] = pmap;
  906.         if (wPreferences.new_style) {
  907.         fwin->lbutton_back[state] = lpmap;
  908.         fwin->rbutton_back[state] = rpmap;
  909. #ifdef XKB_BUTTON_HINT
  910.         fwin->languagebutton_back[state] = tpmap;
  911. #endif
  912.         }
  913.     }
  914.     }
  915.     if (fwin->resizebar_texture && fwin->resizebar_texture[0] 
  916.     && fwin->resizebar && state == 0) {
  917.  
  918.     FREE_PIXMAP(fwin->resizebar_back[0]);
  919.  
  920.     if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
  921.  
  922.         renderResizebarTexture(fwin->screen_ptr,
  923.                    fwin->resizebar_texture[0],
  924.                    fwin->resizebar->width,
  925.                    fwin->resizebar->height,
  926.                    fwin->resizebar_corner_width,
  927.                    &pmap);
  928.  
  929.         fwin->resizebar_back[0] = pmap;
  930.     }
  931.     
  932.     /* this part should be in updateTexture() */
  933.     if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
  934.         XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window,
  935.                        fwin->resizebar_back[0]);
  936.     } else {
  937.         XSetWindowBackground(dpy, fwin->resizebar->window,
  938.                  fwin->resizebar_texture[0]->solid.normal.pixel);
  939.     }
  940.     XClearWindow(dpy, fwin->resizebar->window);
  941.     }
  942. }
  943.  
  944.  
  945. void
  946. wFrameWindowPaint(WFrameWindow *fwin)
  947. {
  948.     WScreen *scr = fwin->screen_ptr;
  949.  
  950.     if (fwin->flags.is_client_window_frame)
  951.     fwin->flags.justification = wPreferences.title_justification;
  952.  
  953.     if (fwin->flags.need_texture_remake) {
  954.     int i;
  955.  
  956.     fwin->flags.need_texture_remake = 0;
  957.     fwin->flags.need_texture_change = 0;
  958.  
  959.     if (fwin->flags.single_texture) {
  960.         remakeTexture(fwin, 0);
  961.         updateTexture(fwin);
  962.     } else {
  963.         /* first render the texture for the current state... */
  964.         remakeTexture(fwin, fwin->flags.state);
  965.         /* ... and paint it */
  966.         updateTexture(fwin);
  967.  
  968.         for (i=0; i < 3; i++) {
  969.         if (i!=fwin->flags.state)
  970.             remakeTexture(fwin, i);
  971.         }
  972.     }
  973.     }
  974.     
  975.     if (fwin->flags.need_texture_change) {    
  976.     fwin->flags.need_texture_change = 0;
  977.     
  978.     updateTexture(fwin);
  979.     }
  980.     
  981.     if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
  982.     && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
  983.     wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
  984.            fwin->titlebar->height,
  985.            (WTexSolid*)fwin->title_texture[fwin->flags.state], 
  986.            WREL_RAISED);
  987.     }
  988.     
  989.     if (fwin->resizebar    && !fwin->flags.repaint_only_titlebar
  990.     && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
  991.     Window win;
  992.     int w, h;
  993.     int cw;
  994.     GC light_gc, dim_gc;
  995.     WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
  996.     
  997.     w = fwin->resizebar->width;
  998.     h = fwin->resizebar->height;
  999.     cw = fwin->resizebar_corner_width;
  1000.     light_gc = texture->light_gc;
  1001.     dim_gc = texture->dim_gc;
  1002.     win = fwin->resizebar->window;
  1003.     
  1004.     XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
  1005.     XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
  1006.     
  1007.     XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
  1008.     XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
  1009.     
  1010.     XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
  1011.     XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
  1012.     
  1013. #ifdef SHADOW_RESIZEBAR
  1014.     XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
  1015.     XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
  1016.     XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
  1017.     XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
  1018.     XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
  1019. #endif /* SHADOW_RESIZEBAR */
  1020.     }
  1021.     
  1022.     
  1023.     if (fwin->title && fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
  1024.         int x, w;
  1025.         int lofs = 6, rofs = 6;
  1026.         int titlelen;
  1027.         char *title;
  1028.         int allButtons = 1;
  1029.  
  1030.  
  1031.         if (!wPreferences.new_style) {
  1032.         if (fwin->left_button && !fwin->flags.hide_left_button
  1033.         && !fwin->flags.lbutton_dont_fit)
  1034.         lofs += fwin->left_button->width + 3;
  1035.         else
  1036.         allButtons = 0;
  1037.  
  1038. #ifdef XKB_BUTTON_HINT
  1039.         if (fwin->language_button && !fwin->flags.hide_language_button
  1040.         && !fwin->flags.languagebutton_dont_fit)
  1041.         lofs += fwin->language_button->width;
  1042.         else
  1043.         allButtons = 0;
  1044. #endif
  1045.         
  1046.         if (fwin->right_button && !fwin->flags.hide_right_button
  1047.         && !fwin->flags.rbutton_dont_fit)
  1048.         rofs += fwin->right_button->width + 3;
  1049.         else
  1050.         allButtons = 0;
  1051.         }
  1052.  
  1053. #ifdef XKB_BUTTON_HINT
  1054.         fwin->languagebutton_image =
  1055.             scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
  1056. #endif
  1057.  
  1058.     title = ShrinkString(*fwin->font, fwin->title,
  1059.                  fwin->titlebar->width - lofs - rofs);
  1060.     titlelen = strlen(title);
  1061.     w = WMWidthOfString(*fwin->font, title, titlelen);
  1062.  
  1063.     switch (fwin->flags.justification) {
  1064.      case WTJ_LEFT:
  1065.         x = lofs;
  1066.         break;
  1067.  
  1068.      case WTJ_RIGHT:
  1069.         x = fwin->titlebar->width - w - rofs;
  1070.         break;
  1071.  
  1072.      default:
  1073.         if (!allButtons)
  1074.         x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
  1075.         else
  1076.         x = (fwin->titlebar->width - w) / 2;
  1077.         break;
  1078.     }
  1079.  
  1080.  
  1081.     XSetForeground(dpy, *fwin->title_gc, 
  1082.                fwin->title_pixel[fwin->flags.state]);
  1083.     
  1084. #ifdef DRAWSTRING_PLUGIN
  1085.     if (scr->drawstring_func[fwin->flags.state + fwin->drawstring_proc_offset]) {
  1086.         scr->drawstring_func[fwin->flags.state + fwin->drawstring_proc_offset]->
  1087.             proc.drawString(scr->drawstring_func[fwin->flags.state 
  1088.                     + fwin->drawstring_proc_offset]->arg,
  1089.                     fwin->titlebar->window, *fwin->title_gc,
  1090.                     *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
  1091.                     fwin->titlebar->width, fwin->top_width, title, titlelen);
  1092.     } else {
  1093.         WMDrawString(scr->wmscreen, fwin->titlebar->window, 
  1094.                 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE, 
  1095.                 title, titlelen);
  1096.     }
  1097. #else
  1098.     WMDrawString(scr->wmscreen, fwin->titlebar->window, 
  1099.             *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE, 
  1100.             title, titlelen);
  1101. #endif /* DRAWSTRING_PLUGIN */
  1102.  
  1103.     free(title);
  1104.     
  1105.     if (fwin->left_button)
  1106.         handleButtonExpose(&fwin->left_button->descriptor, NULL);
  1107.     if (fwin->right_button)
  1108.         handleButtonExpose(&fwin->right_button->descriptor, NULL);
  1109. #ifdef XKB_BUTTON_HINT
  1110.     if (fwin->language_button)
  1111.         handleButtonExpose(&fwin->language_button->descriptor, NULL);
  1112. #endif 
  1113.     }
  1114. }
  1115.  
  1116.  
  1117. static void
  1118. reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
  1119.         Bool dontMove)
  1120. {
  1121.     int k = (wPreferences.new_style ? 4 : 3);
  1122.     int resizedHorizontally = 0;
  1123.     
  1124.     if (dontMove)
  1125.     XResizeWindow(dpy, fwin->core->window, width, height);
  1126.     else
  1127.     XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
  1128.  
  1129.     /*
  1130.      if (fwin->core->height != height && fwin->resizebar)
  1131.      XMoveWindow(dpy, fwin->resizebar->window, 0,
  1132.          height - fwin->resizebar->height);
  1133.      */
  1134.     if (fwin->core->width != width) {
  1135.         fwin->flags.need_texture_remake = 1;
  1136.     resizedHorizontally = 1;
  1137.     }
  1138.     
  1139.     fwin->core->width = width;
  1140.     fwin->core->height = height;
  1141.  
  1142.     if (fwin->titlebar && resizedHorizontally) {    
  1143.     /* Check if the titlebar is wide enough to hold the buttons.
  1144.      * Temporarily remove them if can't
  1145.      */
  1146.     if (fwin->left_button) {
  1147.         if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
  1148.         
  1149.         if (!fwin->flags.hide_left_button) {
  1150.             XUnmapWindow(dpy, fwin->left_button->window);
  1151.         }
  1152.         fwin->flags.lbutton_dont_fit = 1;
  1153.         } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
  1154.         
  1155.         if (!fwin->flags.hide_left_button) {
  1156.             XMapWindow(dpy, fwin->left_button->window);
  1157.         }
  1158.         fwin->flags.lbutton_dont_fit = 0;
  1159.         }
  1160.     }
  1161.     
  1162. #ifdef XKB_BUTTON_HINT
  1163.     if (fwin->language_button) {
  1164.         if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
  1165.         
  1166.         if (!fwin->flags.hide_language_button) {
  1167.             XUnmapWindow(dpy, fwin->language_button->window);
  1168.         }
  1169.         fwin->flags.languagebutton_dont_fit = 1;
  1170.         } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
  1171.         
  1172.         if (!fwin->flags.hide_language_button) {
  1173.             XMapWindow(dpy, fwin->language_button->window);
  1174.         }
  1175.         fwin->flags.languagebutton_dont_fit = 0;
  1176.         }
  1177.     }
  1178. #endif
  1179.     
  1180.     if (fwin->right_button) {
  1181.         if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
  1182.         
  1183.         if (!fwin->flags.hide_right_button) {
  1184.             XUnmapWindow(dpy, fwin->right_button->window);
  1185.         }
  1186.         fwin->flags.rbutton_dont_fit = 1;
  1187.         } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
  1188.         
  1189.         if (!fwin->flags.hide_right_button) {
  1190.             XMapWindow(dpy, fwin->right_button->window);
  1191.         }
  1192.         fwin->flags.rbutton_dont_fit = 0;
  1193.         }
  1194.     }
  1195.     
  1196.         if (wPreferences.new_style) {        
  1197.         if (fwin->right_button)
  1198.         XMoveWindow(dpy, fwin->right_button->window, 
  1199.                 width - fwin->right_button->width + 1, 0);
  1200.         } else {
  1201.         if (fwin->right_button)
  1202.         XMoveWindow(dpy, fwin->right_button->window, 
  1203.                 width - fwin->right_button->width - 3,
  1204.                 (fwin->titlebar->height - fwin->right_button->height)/2);
  1205.         }
  1206.     updateTitlebar(fwin);
  1207.     checkTitleSize(fwin);
  1208.     }
  1209.     
  1210.     if (fwin->resizebar) {
  1211.     wCoreConfigure(fwin->resizebar, 0, 
  1212.                fwin->core->height - fwin->resizebar->height,
  1213.                fwin->core->width, fwin->resizebar->height);
  1214.     
  1215.     fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
  1216.     if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
  1217.         fwin->resizebar_corner_width = fwin->core->width/2;
  1218.     }
  1219.     }
  1220. }
  1221.  
  1222. void 
  1223. wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
  1224. {
  1225.     reconfigure(fwin, x, y, width, height, False);
  1226. }
  1227.  
  1228. void
  1229. wFrameWindowResize(WFrameWindow *fwin, int width, int height)
  1230. {
  1231.     reconfigure(fwin, 0, 0, width, height, True);
  1232. }
  1233.  
  1234.  
  1235.  
  1236. int 
  1237. wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
  1238. {
  1239.     /* check if the title is the same as before */
  1240.     if (fwin->title) {
  1241.         if (new_title && (strcmp(fwin->title, new_title) == 0)) {
  1242.         return 0;
  1243.     }
  1244.     } else {
  1245.         if (!new_title)
  1246.            return 0;
  1247.     }
  1248.  
  1249.     if (fwin->title)
  1250.     free(fwin->title);
  1251.     
  1252.     fwin->title = wstrdup(new_title);
  1253.     
  1254.     if (fwin->titlebar) {
  1255.     XClearWindow(dpy, fwin->titlebar->window);
  1256.  
  1257.     wFrameWindowPaint(fwin);
  1258.     }
  1259.     checkTitleSize(fwin);
  1260.     
  1261.     return 1;
  1262. }
  1263.  
  1264.  
  1265. #ifdef OLWM_HINTS
  1266. void
  1267. wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
  1268. {
  1269.     fwin->flags.right_button_pushed_in = pushed;
  1270.  
  1271.     paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
  1272.         fwin->title_pixel[fwin->flags.state],
  1273.         fwin->rbutton_image, pushed);
  1274. }
  1275. #endif /* OLWM_HINTS */
  1276.  
  1277.  
  1278. #ifdef XKB_BUTTON_HINT
  1279. void
  1280. wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
  1281. {
  1282.     paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
  1283.         fwin->title_pixel[fwin->flags.state],
  1284.         fwin->languagebutton_image, True);
  1285. }
  1286. #endif /* XKB_BUTTON_HINT */
  1287.  
  1288.  
  1289. /*********************************************************************/
  1290.  
  1291. static void 
  1292. handleExpose(WObjDescriptor *desc, XEvent *event)
  1293. {
  1294.     WFrameWindow *fwin = (WFrameWindow*)desc->parent;
  1295.     
  1296.     
  1297.     if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
  1298.     fwin->flags.repaint_only_titlebar = 1;
  1299.     if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
  1300.     fwin->flags.repaint_only_resizebar = 1;
  1301.     wFrameWindowPaint(fwin);
  1302.     fwin->flags.repaint_only_titlebar = 0;
  1303.     fwin->flags.repaint_only_resizebar = 0;
  1304. }
  1305.  
  1306.  
  1307. static void
  1308. checkTitleSize(WFrameWindow *fwin)
  1309. {
  1310.     int width;
  1311.  
  1312.     if (!fwin->title) {
  1313.     fwin->flags.incomplete_title = 0;
  1314.     return;
  1315.     }
  1316.     
  1317.     if (!fwin->titlebar) {
  1318.     fwin->flags.incomplete_title = 1;
  1319.     return;
  1320.     } else {
  1321.     width = fwin->titlebar->width - 6 - 6;
  1322.     }
  1323.  
  1324.     if (!wPreferences.new_style) {
  1325.     if (fwin->left_button && !fwin->flags.hide_left_button
  1326.         && !fwin->flags.lbutton_dont_fit)
  1327.         width -= fwin->left_button->width + 3;
  1328.  
  1329. #ifdef XKB_BUTTON_HINT
  1330.     if (fwin->language_button && !fwin->flags.hide_language_button
  1331.         && !fwin->flags.languagebutton_dont_fit)
  1332.         width -= fwin->language_button->width + 3;
  1333. #endif
  1334.     
  1335.     if (fwin->right_button && !fwin->flags.hide_right_button
  1336.         && !fwin->flags.rbutton_dont_fit)
  1337.         width -= fwin->right_button->width + 3;
  1338.     }
  1339.     if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
  1340.     fwin->flags.incomplete_title = 1;
  1341.     } else {
  1342.     fwin->flags.incomplete_title = 0;
  1343.     }
  1344. }
  1345.  
  1346.  
  1347. static void
  1348. paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
  1349.         WPixmap *image, int pushed)
  1350.     WScreen *scr = button->screen_ptr;
  1351.     GC copy_gc = scr->copy_gc;
  1352.     int x=0, y=0, d=0;
  1353.     int left=0, width=0;
  1354.     
  1355.     /* setup stuff according to the state */
  1356.     if (pushed) {
  1357.     if (image) {
  1358.         if (image->width>=image->height*2) {
  1359.         /* the image contains 2 pictures: the second is for the 
  1360.          * pushed state */
  1361.         width = image->width/2;
  1362.         left = image->width/2;
  1363.         } else {
  1364.         width = image->width;
  1365.         }
  1366.     }
  1367.     XSetClipMask(dpy, copy_gc, None);
  1368.     XSetForeground(dpy, copy_gc, scr->white_pixel);
  1369.     d=1;
  1370.     if (wPreferences.new_style) {
  1371.         XFillRectangle(dpy, button->window, copy_gc, 0, 0,
  1372.                button->width-1, button->height-1);
  1373.         XSetForeground(dpy, copy_gc, scr->black_pixel);
  1374.         XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
  1375.                button->width-1, button->height-1);
  1376.     } else {
  1377.         XFillRectangle(dpy, button->window, copy_gc, 0, 0,
  1378.                button->width, button->height);
  1379.         XSetForeground(dpy, copy_gc, scr->black_pixel);
  1380.         XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
  1381.                button->width, button->height);
  1382.     }
  1383.     } else {
  1384.     XClearWindow(dpy, button->window);
  1385.     
  1386.     if (image) {
  1387.         if (image->width>=image->height*2)
  1388.         width = image->width/2;
  1389.         else
  1390.         width = image->width;
  1391.     }
  1392.     d=0;
  1393.     
  1394.         if (wPreferences.new_style) {
  1395.         if (texture->any.type==WTEX_SOLID || pushed) {
  1396.         wDrawBevel(button->window, button->width, button->height,
  1397.                (WTexSolid*)texture, WREL_RAISED);
  1398.         }
  1399.         } else {
  1400.         wDrawBevel(button->window, button->width, button->height,
  1401.                scr->widget_texture, WREL_RAISED);
  1402.     }
  1403.     }
  1404.     
  1405.     if (image) {
  1406.     /* display image */
  1407.     XSetClipMask(dpy, copy_gc, image->mask);
  1408.     x = (button->width - width)/2 + d;
  1409.     y = (button->height - image->height)/2 + d;
  1410.     XSetClipOrigin(dpy, copy_gc, x-left, y);
  1411.         if (!wPreferences.new_style) {
  1412.         XSetForeground(dpy, copy_gc, scr->black_pixel);
  1413.         if (!pushed) {
  1414.         if (image->depth==1)
  1415.             XCopyPlane(dpy, image->image, button->window, copy_gc,
  1416.                    left, 0, width, image->height, x, y, 1);
  1417.         else
  1418.             XCopyArea(dpy, image->image, button->window, copy_gc,
  1419.                   left, 0, width, image->height, x, y);
  1420.         } else {
  1421.         XSetForeground(dpy, copy_gc, scr->dark_pixel);
  1422.         XFillRectangle(dpy, button->window, copy_gc, 0, 0,
  1423.                    button->width, button->height);
  1424.         }
  1425.         } else {
  1426.         if (pushed) {
  1427.         XSetForeground(dpy, copy_gc, scr->black_pixel);
  1428.         } else {
  1429.         XSetForeground(dpy, copy_gc, color);
  1430.         XSetBackground(dpy, copy_gc, texture->any.color.pixel);
  1431.         }
  1432.         XFillRectangle(dpy, button->window, copy_gc, 0, 0,
  1433.                button->width, button->height);
  1434.         }
  1435.     }
  1436. }
  1437.  
  1438.  
  1439. static void 
  1440. handleButtonExpose(WObjDescriptor *desc, XEvent *event)
  1441. {
  1442.     WFrameWindow *fwin = (WFrameWindow*)desc->parent;
  1443.     WCoreWindow *button = (WCoreWindow*)desc->self;
  1444.  
  1445. #ifdef XKB_BUTTON_HINT
  1446.     if (button == fwin->language_button) {
  1447.         if (wPreferences.modelock){
  1448.             paintButton(button, fwin->title_texture[fwin->flags.state],
  1449.                     fwin->title_pixel[fwin->flags.state],
  1450.                     fwin->languagebutton_image, False);
  1451.         }
  1452.     } else 
  1453. #endif
  1454.     if (button == fwin->left_button) {
  1455.         paintButton(button, fwin->title_texture[fwin->flags.state],
  1456.                 fwin->title_pixel[fwin->flags.state],
  1457.                 fwin->lbutton_image, False);
  1458.     } else {
  1459.         Bool pushed = False;
  1460.  
  1461. #ifdef OLWM_HINTS
  1462.     if (fwin->flags.right_button_pushed_in)
  1463.         pushed = True;
  1464. #endif
  1465.     /* emulate the olwm pushpin in the "out" state */
  1466.     paintButton(button, fwin->title_texture[fwin->flags.state],
  1467.             fwin->title_pixel[fwin->flags.state],
  1468.             fwin->rbutton_image, pushed);
  1469.     }
  1470. }
  1471.  
  1472.  
  1473. static void 
  1474. titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
  1475. {
  1476.     WFrameWindow *fwin = desc->parent;
  1477.     WCoreWindow *titlebar = desc->self;
  1478.     
  1479.     if (IsDoubleClick(fwin->core->screen_ptr, event)) {
  1480.     if (fwin->on_dblclick_titlebar)
  1481.         (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
  1482.     } else {
  1483.     if (fwin->on_mousedown_titlebar)
  1484.         (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
  1485.     }
  1486. }
  1487.  
  1488.  
  1489. static void 
  1490. resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
  1491. {
  1492.     WFrameWindow *fwin = desc->parent;
  1493.     WCoreWindow *resizebar = desc->self;
  1494.     
  1495.     if (fwin->on_mousedown_resizebar)
  1496.     (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
  1497. }
  1498.  
  1499.  
  1500. static void 
  1501. buttonMouseDown(WObjDescriptor *desc, XEvent *event)
  1502. {
  1503.     WFrameWindow *fwin = desc->parent;
  1504.     WCoreWindow *button = desc->self;
  1505.     WPixmap *image;
  1506.     XEvent ev;
  1507.     int done=0, execute=1;
  1508.     WTexture *texture;
  1509.     unsigned long pixel;
  1510.     int clickButton = event->xbutton.button;
  1511.  
  1512.     if (IsDoubleClick(fwin->core->screen_ptr, event)) {
  1513.     if (button == fwin->right_button && fwin->on_dblclick_right) {
  1514.         (*fwin->on_dblclick_right)(button, fwin->child, event);
  1515.     }
  1516.     return;
  1517.     } 
  1518.     
  1519.     if (button == fwin->left_button) {
  1520.     image = fwin->lbutton_image;
  1521.     } else {
  1522.     image = fwin->rbutton_image;
  1523.     } 
  1524. #ifdef XKB_BUTTON_HINT
  1525.     if (button == fwin->language_button) {
  1526.     if (!wPreferences.modelock) return;
  1527.     image = fwin->languagebutton_image;
  1528.     }
  1529. #endif
  1530.     
  1531.     pixel = fwin->title_pixel[fwin->flags.state];
  1532.     texture = fwin->title_texture[fwin->flags.state];
  1533.     paintButton(button, texture, pixel, image, True);
  1534.     
  1535.     while (!done) {
  1536.     WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
  1537.             |ButtonPressMask|ExposureMask, &ev);
  1538.     switch (ev.type) {
  1539.      case LeaveNotify:
  1540.         execute = 0;
  1541.         paintButton(button, texture, pixel, image, False);
  1542.         break;
  1543.         
  1544.      case EnterNotify:
  1545.         execute = 1;
  1546.         paintButton(button, texture, pixel, image, True);
  1547.         break;
  1548.  
  1549.      case ButtonPress:
  1550.         break;
  1551.  
  1552.        case ButtonRelease:
  1553.         if (ev.xbutton.button == clickButton)
  1554.         done = 1;
  1555.         break;
  1556.         
  1557.      default:
  1558.         WMHandleEvent(&ev);
  1559.     }
  1560.     }
  1561.     paintButton(button, texture, pixel, image, False);
  1562.     
  1563.     if (execute) {
  1564.     if (button == fwin->left_button) {
  1565.         if (fwin->on_click_left)
  1566.         (*fwin->on_click_left)(button, fwin->child, &ev);
  1567.     } else if (button == fwin->right_button) {
  1568.         if (fwin->on_click_right)
  1569.         (*fwin->on_click_right)(button, fwin->child, &ev);
  1570.     }
  1571. #ifdef XKB_BUTTON_HINT
  1572.     else if (button == fwin->language_button) {
  1573.         if (fwin->on_click_language)
  1574.         (*fwin->on_click_language)(button, fwin->child, &ev);
  1575.     }
  1576. #endif
  1577.  
  1578.     }
  1579. }
  1580.  
  1581.